using UnityEngine;

public class PlayerMoverment : MonoBehaviour
{
    private Player player; // 主角对象

    private PlayerControlls controls; // 控制器，用于连接unity新输入系统
    private CharacterController characterController; // 角色控制器，用于角色移动
    private Animator animator; // 角色动画器

    [Header("Movement info")]
    [SerializeField] public float walkSpeed; // 行走速度
    [SerializeField] private float runSpeed; // 跑步速度
    [SerializeField] private float turnSpeed;
    private float speed; // 移动速度
    private float verticalVelocity; // 垂直方向速度

    private Vector3 movementDirection; // 移动方向
    private Vector2 moveInput; // 移动输入

    private bool isRunning; // 是否跑步状态

    private void Start()
    {
        player = GetComponent<Player>();

        characterController = GetComponent<CharacterController>();
        animator = GetComponentInChildren<Animator>();

        speed = walkSpeed;

        AssignInputEvents();
    }

    private void Update()
    {
        ApplyMovement(); // 角色移动
        ApplyRotation(); // 角色瞄准鼠标
        AnimatorControllers(); // 角色控制动画
    }

    private void AnimatorControllers()
    {
        // movementDirection.normalized的范围是从(1, 0, 0)到(-1, 0, 0), transform.right一直是(1, 0, 0), 点积结果范围就是1到-1，用他们的点积计算角色向左还是向右
        float xVelocity = Vector3.Dot(movementDirection.normalized, transform.right);
        float zVelocity = Vector3.Dot(movementDirection.normalized, transform.forward);

        animator.SetFloat("xVelocity", xVelocity, .1f, Time.deltaTime);
        animator.SetFloat("zVelocity", zVelocity, .1f, Time.deltaTime);

        bool playRunAnimation = isRunning && movementDirection.magnitude > 0;
        animator.SetBool("isRunning", playRunAnimation);
    }

    private void ApplyRotation()
    {
        Vector3 lookingDirection = player.aim.GetMousePosition() - transform.position;
        lookingDirection.y = 0f;
        lookingDirection.Normalize();

        Quaternion desiredRotation = Quaternion.LookRotation(lookingDirection);
        transform.rotation = Quaternion.Slerp(transform.rotation, desiredRotation, turnSpeed * Time.deltaTime);
    }

    private void ApplyMovement()
    {
        movementDirection = new Vector3(moveInput.x, 0, moveInput.y);
        ApplyGravity();

        if (movementDirection.magnitude > 0)
        {
            characterController.Move(movementDirection * Time.deltaTime * speed);
        }
    }

    private void ApplyGravity()
    {
        if (characterController.isGrounded == false)
        {
            verticalVelocity -= 9.81f * Time.deltaTime;
            movementDirection.y = verticalVelocity;
        }
        else
            verticalVelocity = -.5f;
    }

    private void AssignInputEvents()
    {
        controls = player.controls;

        controls.Charactor.Movement.performed += context => moveInput = context.ReadValue<Vector2>();
        controls.Charactor.Movement.canceled += context => moveInput = Vector2.zero;

        controls.Charactor.Run.performed += context =>
        {
            speed = runSpeed;
            isRunning = true;
        };
        controls.Charactor.Run.canceled += context =>
        {
            speed = walkSpeed;
            isRunning = false;
        };
    }
}
